/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "owndebug.h"
#include "ownutils.h"
#include "gimutils.h"
#include "MaCICtrlServer.hpp"
#include "Player.hpp"
#include "PlayerModuleGenerator.hpp"
#include <iostream>
#include <sstream>
// Include GIMI in proper way
#define GIMI_CLIENT_API (20000)
#include "gimi.h"

static void showUsage()
{
  fprintf(stderr,"\n");
  fprintf(stderr,"Usage:\tCMaCIPlayer_terminal [OPTIONS]\n");
  fprintf(stderr,"  [-u addr]\t\t\tUse 'addr' as GIMnet AccessPoints address\n");
  fprintf(stderr,"  [-p port]\t\t\tUse 'port' as GIMnet AccessPoints port\n");
  fprintf(stderr,"  [-g name]\t\t\tThe gimnet id of the Gimbo instance this component is created by\n");
  fprintf(stderr,"  [-f filename]\t\t\tFilename to play(Use multiple [-f filename] to have multiple files)\n");
  fprintf(stderr,"  [-r]\t\t\t\tRepeat playing \n");
  fprintf(stderr,"  [-s playinSpeed]\t\tPlaying speed multiplier\n");

  fprintf(stderr,"  [-v]\t\t\t\tIncrease verbosity by 1\n");
  fprintf(stderr,"  [-q]\t\t\t\tQuiet mode\n");
  fprintf(stderr, "\n\n");
}
std::string GetStringOfTime(gim::time aTime){
  using namespace std;
  stringstream totalTime (stringstream::in | stringstream::out);

  struct tm aTm;
  aTime.getLocalTime(aTm);
  if(aTime.getSeconds()> 60*60){
    long int sec = aTime.getSeconds();
    
    sec = sec /3600;
    totalTime << sec <<":";
  }
  if(aTm.tm_min < 10){
    totalTime << "0" <<aTm.tm_min <<":";
  }else{
    totalTime <<aTm.tm_min <<":";
  }
  
  if(aTm.tm_sec <10){
    totalTime << "0" <<aTm.tm_sec;
  }else{
    totalTime << aTm.tm_sec;
  }

  return totalTime.str();
}


int main(int argc, char *argv[]) {
  // GIMnet parameters
  // Objects
  
  std::string gimnetAP;
  int gimnetAPPort;
  int verbose = 0;  
  std::string gimnetName = "";

  // Init Debug lib
  // Objects
  //  bool run = true;
  gimi::GIMI g;
  
  std::string macigroupname = "MaCI_Player";
  // Init Debug lib
  debugInit();
  debugSetGlobalDebugLvl(1);
  //debugSetLogFilename("MaCI_Player.log");
  //Application variables
  std::vector<std::string> filenames;
  bool repeat = false;
  float playingSpeed = 1;
  // Greet
  fprintf(stderr,
	  "\nMaCI_Player_Terminal - MaCI:player terminal version - version 0.1 Beta\n\n");

  // Parse parameters
  bool parse = true;
  while(parse) {
    int c;
    c = getopt(argc, argv, "f:g:G:s:n:u:p:hqvr");
    switch(c) {

      /////////////////////////////////
      ////// Application specific /////
      /////////////////////////////////
    case 'r':
      repeat = true;
      dPrint(1,"Using repeat");
      break;
    case 's':
      playingSpeed =  atof(optarg);
      dPrint(1,"Using playing speed %f",playingSpeed);
      break;
      /////////////////////////////////
      ///// GIMnet parameters /////////
      /////////////////////////////////


    case 'n':
      gimnetName = optarg;
      dPrint(1,"Using GIMnet Name '%s'", optarg);
      break;

    case 'u':
      gimnetAP = optarg;
      dPrint(1,"Using GIMnetAP address '%s'", optarg);
      break;

    case 'p':
      gimnetAPPort = atoi(optarg);
      dPrint(1,"Using GIMnetAP port '%d'", gimnetAPPort);
      break;
    case 'f':
      dPrint(1,"Using file '%s'",optarg);
      filenames.push_back(std::string(optarg));
      break;
    case 'g':
    case 'G':
      macigroupname = optarg;
      break;

      //////////////////////////////////
      //// GENERIC:                 ////
      //////////////////////////////////
    case 'v':
      // Increase only if not previously set to 0 (by 'quiet')
      if (verbose > 0)
	debugSetGlobalDebugLvl(++verbose);
      break;
      
    case 'q':
      verbose = 0;
      debugSetGlobalDebugLvl(0);
      break;
      
    case 'h':
    case '?':
      showUsage();
      exit(1);
      break;
      
    case -1:
      parse = false;
      break;
    }
  }



  int r;
  if ( (r = g.connectToHubEx(gimnetAP, gimnetAPPort, gimnetName) ) != GIMI_OK) {
    dPrint(1,"Failed to connect to GIMnet AccessPoint '%s:%d' with name '%s': '%s'",
	   gimnetAP.c_str(), 
	   gimnetAPPort, 
	   gimnetName.size()?gimnetName.c_str():"<anonymous>",
	   gimi::getGimiErrorString(r).c_str());
    
  } else {
    dPrint(2,"Succesfully connected to GIMnet at AccessPoint '%s:%d' with name '%s': '%s'",
	   gimnetAP.c_str(), 
	   gimnetAPPort, 
	   gimnetName.size()?gimnetName.c_str():"<anonymous>",
	   gimi::getGimiErrorString(r).c_str());
    ownSleep_ms(500);
    MaCI::MaCICtrl::CMaCICtrlServer MaCICtrlServer(&g);
    
    MaCICtrlServer.SetGroupName(macigroupname);
    PlayerModuleGenerator generator;
    Player player;
    for(EACH_IN_i(filenames)){
      
      PlayerModule *module = generator.GenerateNewPlayerModule(*i,&MaCICtrlServer);
      if(module){
        player.SetPlayerModule(module);
      }
    }
    gim::time begin,end,totaltime;
    player.GetTimeLimits(begin,end);
    totaltime = end-begin;
    
    dPrint(1,"Total playing time '%s'",GetStringOfTime(totaltime).c_str());

    //Set repeat mode on/off
    player.SetRepeat(repeat);
    player.SetPlayingSpeed(playingSpeed);
    player.StartPlaying(); 
    gim::time current;
    float ratio;
    while(player.IsPlaying()){
      ownSleep_ms(1000);
      player.GetCurrentTime(current,ratio);
      dPrint(1,"%s of %s. %f %% played", GetStringOfTime(current).c_str(),GetStringOfTime(totaltime).c_str(),ratio*100);

    }
  }

  g.stop();
  return 0;

}
